#include<iostream>
#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
#include<cerrno>
#include<string.h>
#include<string>
#include<time.h>
using namespace std;


int main()
{
    return 0;
}

///////////////////////////////
// 互斥锁：动态、局部法
int tickets = 10000;
#define THREAD_NUM 5 //待创建线程数目


class ThreadData // 用于创建线程时，args传参：线程名、锁
{
public:
    ThreadData(const string &name, pthread_mutex_t *pmutex)
        : _name(name), _pmutex(pmutex)
    {}

    string _name;
    pthread_mutex_t* _pmutex;
};


void *getTickets(void *args)
{
    ThreadData* td = (ThreadData*)args;
    while(true)
    {
        //3、加锁：
        pthread_mutex_lock(td->_pmutex);
        if(tickets > 0 )
        {
            usleep(rand() % 1500);//休眠:让休眠随机一点
            printf("%s: %d\n", td->_name.c_str(), tickets--);
            pthread_mutex_lock(td->_pmutex);
            pthread_mutex_unlock(td->_pmutex);//3、解锁
        }
        else 
        {
            pthread_mutex_unlock(td->_pmutex);//3、解锁
            break;
        }
    }
    delete td;//销毁new出来的空间
    return nullptr;
}



int main()
{
    srand((unsigned int)time(nullptr) ^ getpid()); // 种子：用于让持锁线程更加随机
    clock_t t1 = clock();                          // 测试时间

    pthread_mutex_t mutex;                         // 1、定义一个锁
    pthread_mutex_init(&mutex, nullptr);           // 2、对锁初始化

    // 创建线程
    pthread_t tid[THREAD_NUM]; // 线程ID
    for (int i = 0; i < THREAD_NUM; ++i)
    {
        string name = "thread";        // 线程名
        name += std::to_string(i + 1); // 线程名
        ThreadData *td = new ThreadData(name, &mutex);
        pthread_create(tid + i, nullptr, getTickets, (void *)td);
    }

    // 等待线程
    for (int i = 0; i < THREAD_NUM; ++i)
    {
        pthread_join(tid[i], nullptr);
    }

    //4、销毁锁
    pthread_mutex_destroy(&mutex);

    clock_t t2 = clock();
    cout << "time: " << (t2 - t1) << endl;

    return 0;
}
///////////////////////////////










///////////////////////////////
//互斥锁：静态、全局法
int tickets = 10000;

//1、定义一个锁并对其初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* getTickets(void* args)
{
    (void)args;
    while(true)
    {
        //2、加锁：
        pthread_mutex_lock(&mutex);
        if(tickets > 0 )
        {
            usleep(rand() % 1500);//休眠:让休眠随机一点
            printf("%p: %d\n", pthread_self(), tickets--);
            pthread_mutex_unlock(&mutex);//3、解锁
        }
        else 
        {
            pthread_mutex_unlock(&mutex);//3、解锁
            break;
        }
    }
    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr)^getpid());//种子：用于让持锁线程更加随机
    clock_t t1 = clock();//测试时间

    pthread_t tid1, tid2, tid3;//一次创建多个线程
    pthread_create(&tid1, nullptr, getTickets, nullptr);
    pthread_create(&tid2, nullptr, getTickets, nullptr);
    pthread_create(&tid3, nullptr, getTickets, nullptr);

    pthread_join(tid1, nullptr);
    pthread_join(tid2, nullptr);
    pthread_join(tid3, nullptr);

    clock_t t2 = clock();
    cout << "time: "<< (t2-t1) << endl;

    return 0;
}
///////////////////////////////




///////////////////////////////
//线程互斥：演示不加保护下，多线程抢票
int tickets = 1000;

void* getTickets(void* args)
{
    (void)args;
    while(true)
    {
        if(tickets > 0 )
        {
            usleep(1000);//休眠
            printf("%p: %d\n", pthread_self(), tickets--);
        }
        else break;
    }
    return nullptr;
}

int main()
{
    pthread_t tid1, tid2, tid3;//一次创建多个线程
    pthread_create(&tid1, nullptr, getTickets, nullptr);
    pthread_create(&tid2, nullptr, getTickets, nullptr);
    pthread_create(&tid3, nullptr, getTickets, nullptr);

    pthread_join(tid1, nullptr);
    pthread_join(tid2, nullptr);
    pthread_join(tid3, nullptr);

    return 0;
}
///////////////////////////////




///////////////////////////////
//线程分离演示
void* Routine(void* args)
{
    //可以是线程组内其他线程对目标线程进行分离，也可以是线程自己分离
    pthread_detach(pthread_self());

    int count = 5;
    while(count--)
    {
        int a = 5;
        a /= 0;//error:演示线程分离异常
        printf("new thread,tid:%u, count:%d\n",pthread_self(),count);
        sleep(1);
    }
    return nullptr;
}

int main()
{
    pthread_t tid = 0;
    pthread_create(&tid, nullptr, Routine, (void*)"new thread");

    int count = 20;
    while(count--)
    {
        printf("main thread, tid:%u, count:%d\n",pthread_self(),count);
        sleep(1);
    }
    cout <<"thr result：" << strerror(pthread_join(tid ,nullptr)) << endl;

    return 0;
}
///////////////////////////////





///////////////////////////////
// 演示在线程中使用进程替换
void* Routine(void* args)
{
    while(true)
    {
        sleep(3);
        execl("/bin/ls","ls",nullptr);//进程替换


        printf("new thread,tid:%u\n",pthread_self());
        sleep(1);
    }
}

int main()
{
    pthread_t tid = 0;
    pthread_create(&tid, nullptr, Routine, (void*)"new thread");

    while(true)
    {
        printf("main thread,tid:%u\n",pthread_self());
        sleep(1);
    }
    pthread_join(tid ,nullptr);

    return 0;
}
///////////////////////////////





///////////////////////////////
//演示全局变量共享：__thread关键字
__thread int val = 0;

void* Routine(void* args)
{
    while(true)
    {
        //cout << "new  thread," << ", val:" << val << ", &val:" << &val << endl;
        printf("new  thread, val:%d, &val:%p\n",val,&val);
        val++;
        sleep(1);
    }
}

int main()
{
    pthread_t tid = 0;
    pthread_create(&tid, nullptr, Routine, (void*)"new thread");

    while(true)
    {
        //cout << "main thread" << ", val:" << val << ", &val:" << &val << endl;
        printf("main thread, val:%d, &val:%p\n",val,&val);
        sleep(1);
    }
    pthread_join(tid ,nullptr);

    return 0;
}
///////////////////////////////





///////////////////////////////
//线程ID探索；pthread_t pthread_self(void);
void* pthreadRoutine(void * args)
{
    size_t count = 3;
    while(count--)    
    {
       cout << (char*)args << ": runing." << "  tid:" << pthread_self() << endl;
       sleep(1);
    }
    cout << "new thread: quit." << endl;
    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, pthreadRoutine, (void*)"new thread");//创建新线程

    pthread_join(tid, nullptr);//阻塞式等待新线程

    int count = 3;//让主线程在新线程退出后再运行一段时间
    while(count--)
    {
        cout << "main thread: runing."  "  tid:" << pthread_self() << endl;
        sleep(1);
    }
    cout << "main quit." << endl;
    return 0;
}
///////////////////////////////





///////////////////////////////
//线程终止：pthread_cancel
void* pthreadRoutine(void * args)
{
    cout << (char*)args << ": runing." << endl;
    size_t count = 0;
    while(true)//让新线程一直循环运行
    {
        cout << "new thread: " << count++ << endl;
        sleep(1);
    }

    cout << "new thread: quit." << endl;
    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, pthreadRoutine, (void*)"new thread");
    cout << "main thread: create succeed." << endl;

    sleep(6);//让新线程运行6s后，取消新线程。
    pthread_cancel(tid);

    int* ret = nullptr;
    pthread_join(tid, (void**)&ret);//阻塞式等待,接收来自pthread_cancel的返回值
    cout << "main thread: wait succeed, the return value:" << (long long)ret <<" ,tid:" << tid << endl;

    int count = 5;//让主线程在新线程退出后再运行一段时间
    while(count--)
    {
        cout << " main thread: runing." << endl;
        sleep(1);
    }
    cout << "main quit." << endl;
    return 0;
}
///////////////////////////////





///////////////////////////////
//线程终止：exit、pthread_exit
void* pthreadRoutine(void * args)
{
    cout << (char*)args << ": runing." << endl;

    int* data = new int[5];
    for(int count = 0 ; count < 5; ++count)
    {
        cout << "new thread: " << count << endl;
        data[count] = count;
        sleep(1);
    }
    cout<< "now, exit the new thread." << endl;
    pthread_exit((void*)11);//使用exit终止新线程

    cout << "new thread: quit." << endl;
    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, pthreadRoutine, (void*)"new thread");
    cout << "main thread: create succeed." << endl;

    int* ret = nullptr;
    pthread_join(tid, (void**)&ret);//阻塞式等待,接收来自pthread_exit的返回值
    cout << "main thread: wait succeed, the return value:" << (long long)ret << endl;
    while(true)
    {
        cout << " main still runing." << endl;
        sleep(1);
    }

    return 0;
}
///////////////////////////////




///////////////////////////////
//线程等待，演示三：演示线程返回值
void* pthreadRoutine(void * args)
{
    cout << (char*)args << ": runing." << endl;

    int* data = new int[5];
    for(int count = 0 ; count < 5; ++count)
    {
        cout << "new thread: " << count << endl;
        data[count] = count;
        sleep(1);
    }

    cout << "new thread: quit." << endl;
    return (void*)data;//返回了堆上申请的空间（新线程）
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, pthreadRoutine, (void*)"new thread");
    cout << "main thread: create succeed." << endl;

    int* ret = nullptr;//用于接收pthreadRoutine，新线程返回值

    pthread_join(tid, (void**)&ret);
    cout << "main thread: wait succeed." << endl;

    for(int i = 0; i < 5; ++i)
    {
        cout << ret[i] << ' ';
    }
    cout << endl;
    return 0;
}
///////////////////////////////





///////////////////////////////
//线程等待，演示二：演示线程返回值
void* pthreadRoutine(void * args)
{
    cout << (char*)args << ": runing." << endl;

    int count = 5;
    do{
        cout << "new thread: " << count << endl;
        sleep(1);
    }while(count--);

    cout << "new thread: quit." << endl;
    return (void*)22;//22，从整形转变为void*类型，相当于将地址数据为22处返回。
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, pthreadRoutine, (void*)"new thread");
    cout << "main thread: create succeed." << endl;

    void* ret = nullptr;//用于接收pthreadRoutine，新线程返回值

    pthread_join(tid, &ret);
    cout << "ret: " << ret << " , ret:" << (long long)ret <<endl;
    cout << "main thread: wait succeed, main quit." << endl;
    return 0;
}
///////////////////////////////






///////////////////////////////
//线程等待，演示一：可验证退出有序
void* pthreadRoutine(void * args)
{
    cout << (char*)args << ": runing." << endl;

    int count = 5;
    do{
        cout << "new thread: " << count << endl;
        sleep(1);
    }while(count--);

    cout << "new thread: quit." << endl;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, pthreadRoutine, (void*)"new thread");
    cout << "main thread: create succeed." << endl;
    pthread_join(tid, nullptr);
    cout << "main thread: wait succeed, main quit." << endl;
    return 0;
}
///////////////////////////////




///////////////////////////////
//线程异常演示：除零错误
void* threadRoutine(void * args)
{
    while(true)
    {
        sleep(2);
        cout << "新线程： " << (char*)args << " , is runing. " << endl;
        
        int a = 10;
        a /= 0 ;//error
    }
}

int main()
{
    fflush(stdout);
    pthread_t tid; // 创建一个线程

    pthread_create(&tid, nullptr, threadRoutine, (void *)"new thread");

    while (true)
    {
        cout << " main thread , pid:" << getpid() << endl;
        sleep(1);
    }
    return 0;
}
///////////////////////////////





///////////////////////////////
//线程概念
void* threadRun(void * args)
{
    string name = (char*)args;//字符串首元素地址、赋值运算符
    while(true)
    {
        cout << name << " , pid:" << getpid() << "\n" << endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid[5];//创建5个线程
    char threadname[64];//用于arg参数传递线程名称，以便区分
    for(int i = 0; i < 5; ++ i)
    {
        //snprintf每次都会向threadname数组中写入字符串。（thread-1、thread-2、thread-3、……）
        snprintf(threadname, sizeof(threadname) ,"%s-%d","thread",i);
        pthread_create(tid+i, nullptr, threadRun, (void*)threadname);
        sleep(1);//此处是缓解传参BUG
    }

    while(true)
    {
        cout << " main thread , pid:" << getpid() << endl;
        sleep(3);
    }
    return 0;
}
///////////////////////////////


